package admin

import (
	"fmt"
	"pfl/db"
	"pfl/models"
	"pfl/utils"
	"regexp"
	"strconv"
	"strings"
	"time"

	"github.com/astaxie/beego"
)

type UserController struct {
	beego.Controller
}

func GetUserIdBySessionU(c *UserController) (int, bool) {
	str := c.Ctx.Input.Session(SessionKey)
	if str == nil {
		return 0, false
	}
	strs := strings.Split(str.(string), ":")
	if strs == nil || len(strs) != 4 {
		return 0, false
	}
	id, err := strconv.Atoi(strs[1])
	if err != nil {
		return 0, false
	}
	return id, true
}

// 列表
func (c *UserController) Get() {
	id, ok := GetUserIdBySessionU(c)
	if !ok {
		c.Redirect("/", 302)
		return
	}
	c.Data["Id"] = id
	c.TplName = "admin/user.html"
}

// 添加
func (c *UserController) Add() {
	id, ok := GetUserIdBySessionU(c)
	if !ok {
		c.Redirect("/", 302)
		return
	}
	c.Data["Id"] = id
	c.TplName = "admin/user_add.html"
}

// 修改
func (c *UserController) Edit() {
	Id, _ := c.GetInt(":id")
	if Id == 0 {
		c.Redirect("/login", 302)
		return
	}

	user := &models.User{Id: Id}
	ok, _ := db.Mysql.Get(user)
	if !ok {
		c.Redirect("/login", 302)
		return
	}
	c.Data["Id"] = Id
	c.Data["User"] = user
	c.TplName = "admin/user_edit.html"
}

func (c *UserController) EditSelf() {
	Id, _ := c.GetInt(":id")
	if Id == 0 {
		c.Redirect("/login", 302)
		return
	}

	user := &models.User{Id: Id}
	ok, _ := db.Mysql.Get(user)
	if !ok {
		c.Redirect("/login", 302)
		return
	}
	c.Data["Id"] = Id
	c.Data["User"] = user
	c.TplName = "admin/user_edit_self.html"
}

func (c *UserController) EditSelfPwd() {
	Id, _ := c.GetInt(":id")
	if Id == 0 {
		c.Redirect("/login", 302)
		return
	}

	user := &models.User{Id: Id}
	ok, _ := db.Mysql.Get(user)
	if !ok {
		c.Redirect("/login", 302)
		return
	}
	c.Data["Id"] = Id
	c.TplName = "admin/user_edit_self_pwd.html"
}

//校验是否是邮箱地址
//param [email string](一个可能是邮箱地址的字符串)
//return bool [true 不存在],[false:存在]
func IsEmail(email string) bool {
	reg := regexp.MustCompile(`\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*`)
	return reg.MatchString(email)
}

//查询数据库是否存在该账户
//param [num string](用户账号)
//return bool [true 不存在],[false:存在]
func checknum(num string) bool {
	if len(strings.Split(num, ":")) > 1 {
		return false
	}
	user := &models.User{}
	ok, err := db.Mysql.Where("Num=?", num).Get(user)
	if !ok && err == nil {
		return true
	} else {
		return false
	}
}

//取得用户的Num通过session
//param [c *UserController]
//return string,bool [成功：num，true][失败:"",false]
func GetUserNumBySession(c *UserController) (string, bool) {
	str := c.Ctx.Input.Session(SessionKey)
	if str == nil {
		return "", false
	}
	strs := strings.Split(str.(string), ":")
	if strs == nil || len(strs) != 4 {
		return "", false
	}
	return strs[0], true
}

//检查用户是否存在
//param [num string](账号)
func (c *UserController) CheckNum() {
	num := c.GetString("num")
	if num == "" || len(num) > 16 {
		c.Ctx.ResponseWriter.Write(utils.JsonToBytes(2, 0, "")) //请正确输入用户名
		return
	}

	if checknum(num) {
		c.Ctx.ResponseWriter.Write(utils.JsonToBytes(0, 0, ""))
	} else {
		c.Ctx.ResponseWriter.Write(utils.JsonToBytes(1, 0, ""))
	}
}

//检查是否是超级管理员
//return bool [true 是],[false:不是]
func checkIsSuperAdmin(c *UserController) bool {
	num, ok := GetUserNumBySession(c)
	if !ok {
		return false
	}
	if num != "admin" {
		return false
	}
	return true
}

func GetOneuser(id int) *models.User {
	user := &models.User{Id: id}
	ok, err := db.Mysql.Get(user)
	if !ok || err != nil {
		return nil
	} else {
		return user
	}
}

//添加一个用户
//param [num string](账号)
//param [pwd string](密码)
//param [name string](名称)
//param [phone string](手机号码)
//param [email string](邮箱)
func (c *UserController) CheckNew() {
	if !checkIsSuperAdmin(c) {
		c.Ctx.ResponseWriter.Write(utils.JsonToBytes(6, 0, ""))
		return
	}
	num := c.GetString("num")
	pwd := c.GetString("pwd")
	name := c.GetString("name")
	if num == "" || pwd == "" || name == "" || len(num) > 16 || len(pwd) != 32 || len(name) > 20 {
		c.Ctx.ResponseWriter.Write(utils.JsonToBytes(0, 0, ""))
		return
	}
	phone := c.GetString("phone")
	email := c.GetString("email")
	if email != "" && !IsEmail(email) {
		c.Ctx.ResponseWriter.Write(utils.JsonToBytes(4, 0, "")) //邮箱地址不对
		return
	}

	if checknum(num) { //谨防伪造出错
		newuser := &models.User{
			Num:        num,
			Pwd:        pwd,
			Createtime: time.Now(),
			Username:   name,
			Phone:      phone,
			Email:      email,
			Status:     0, //1为不可登陆
			Power:      1, //0为超级管理员，1为普通管理员，超级管理员管理所有普通管理员
		}

		rows, err := db.Mysql.InsertOne(newuser)
		if rows != 1 || err != nil {
			c.Ctx.ResponseWriter.Write(utils.JsonToBytes(3, 0, "")) //插入失败
		} else {
			InsertOperationLog(c.Ctx, 0, newuser.Id, L_AddUser)
			c.Ctx.ResponseWriter.Write(utils.JsonToBytes(1, 0, ""))
		}

	} else {
		c.Ctx.ResponseWriter.Write(utils.JsonToBytes(2, 0, ""))
	}

}

//删除一个用户
//param [id int](用户Id)
func (c *UserController) DeleteOne() {
	if !checkIsSuperAdmin(c) {
		c.Ctx.ResponseWriter.Write(utils.JsonToBytes(6, 0, ""))
		return
	}
	id, err := c.GetInt("id")
	if id == 0 {
		c.Ctx.ResponseWriter.Write(utils.JsonToBytes(0, 0, "")) //无效的用户ID
		return
	}
	user := &models.User{}
	rows, err := db.Mysql.Id(id).Delete(user)
	if rows != 1 || err != nil {
		c.Ctx.ResponseWriter.Write(utils.JsonToBytes(2, 0, "")) //删除失败
	} else {
		InsertOperationLog(c.Ctx, 0, id, L_DeleteUser)
		c.Ctx.ResponseWriter.Write(utils.JsonToBytes(1, 0, "")) //删除成功
	}
}

//分页获取用户列表
//param [s int](开始的地方)
//param [c int](取多少个)
//param [n string](查询的关键字,可以为"")
func (c *UserController) GetList() {
	if !checkIsSuperAdmin(c) {
		c.Ctx.ResponseWriter.Write(utils.JsonToBytes(6, 0, ""))
		return
	}
	start, _ := c.GetInt("s")
	if start < 1 {
		start = 1
	}
	count, _ := c.GetInt("c")
	name := c.GetString("n")
	if count == 0 {
		c.Ctx.ResponseWriter.Write(utils.JsonToBytes(2, 0, "")) //无效的参数
		return
	}
	user := &models.User{}
	var CountUsers int64
	var err error
	if name == "" {
		CountUsers, err = db.Mysql.Where("Power != ?", 0).Count(user)
	} else {
		CountUsers, err = db.Mysql.Where(fmt.Sprintf("Power != ? And Username like '%%%s%%'", name), 0).Count(user)
	}
	if err != nil {
		c.Ctx.ResponseWriter.Write(utils.JsonToBytes(0, 0, err)) //查询错误
		return
	}
	us := make([]models.User, 0)
	startindex := (start - 1) * count
	if name == "" {
		err = db.Mysql.Where("Power != ? Limit ?,?", 0, startindex, count).Find(&us)
	} else {
		err = db.Mysql.Where(fmt.Sprintf("Power != ? And Username like '%%%s%%'", name), 0).Limit(count, startindex).Find(&us)
	}

	if err == nil {
		c.Ctx.ResponseWriter.Write(utils.JsonToBytes(1, int(CountUsers), us)) //OK
	} else {
		c.Ctx.ResponseWriter.Write(utils.JsonToBytes(0, 0, "")) //查询错误
	}
}

//更新一个用户的资料，不是跟新自己的资料
//param [id int](用户id)
//param [name string](名称)
//param [phone string](手机号码)
//param [email string](邮箱)
func (c *UserController) UpdateOne() {
	if !checkIsSuperAdmin(c) {
		c.Ctx.ResponseWriter.Write(utils.JsonToBytes(6, 0, ""))
		return
	}
	Id, _ := c.GetInt("id")
	if Id == 0 {
		c.Ctx.ResponseWriter.Write(utils.JsonToBytes(2, 0, "")) //参数错误
		return
	}
	name := c.GetString("name")
	phone := c.GetString("phone")
	email := c.GetString("email")
	user := &models.User{Username: name, Phone: phone, Email: email}
	sess := db.Mysql.NewSession()
	defer sess.Close()
	sess.Begin()
	rows, err := sess.Id(Id).Update(user)
	if rows != 1 || err != nil {
		c.Ctx.ResponseWriter.Write(utils.JsonToBytes(0, 0, "")) //更新失败
		sess.Rollback()
		return
	}
	sess.Commit()
	InsertOperationLog(c.Ctx, 0, Id, L_EditUser)
	db.Mysql.Id(Id).Get(user)
	c.Ctx.ResponseWriter.Write(utils.JsonToBytes(1, 1, user))
}

//检查是不是自己
//param [c *UserController]
//param [id int](用户的id)
//return bool [true 是自己][false 不是自己]
func checkIsSelf(c *UserController, id int) bool {
	sid, ok := GetUserIdBySessionU(c)
	if !ok {
		return false
	}
	if sid != id {
		return false
	}
	return true
}

//更新自己的资料
//param [id int](用户id)
//param [name string](名称)
//param [phone string](手机号码)
//param [email string](邮箱)
func (c *UserController) UpdateSelf() {
	Id, _ := c.GetInt("id")
	if Id == 0 || !checkIsSelf(c, Id) {
		c.Ctx.ResponseWriter.Write(utils.JsonToBytes(6, 0, ""))
		return
	}
	name := c.GetString("name")
	phone := c.GetString("phone")
	email := c.GetString("email")
	user := &models.User{Username: name, Phone: phone, Email: email}
	sess := db.Mysql.NewSession()
	defer sess.Close()
	sess.Begin()
	rows, err := sess.Id(Id).MustCols("Username", "Phone", "Email").Update(user)
	if rows != 1 || err != nil {
		c.Ctx.ResponseWriter.Write(utils.JsonToBytes(0, 0, "")) //更新失败
		sess.Rollback()
		return
	}
	sess.Commit()
	InsertOperationLog(c.Ctx, Id, Id, L_EditUser)
	db.Mysql.Id(Id).Get(user)
	c.Ctx.ResponseWriter.Write(utils.JsonToBytes(1, 1, user))
}

//超级管理员禁用一个账户
//param [id int]
//param [fbd int](1为禁用，0为解禁)
func (c *UserController) ForbiddenOne() {
	if !checkIsSuperAdmin(c) {
		c.Ctx.ResponseWriter.Write(utils.JsonToBytes(6, 0, ""))
		return
	}

	if Id, _ := c.GetInt("id"); Id == 0 {
		c.Ctx.ResponseWriter.Write(utils.JsonToBytes(6, 0, ""))
	} else {
		if fbd, err := c.GetInt("fbd"); err != nil || fbd > 1 || fbd < 0 {
			c.Ctx.ResponseWriter.Write(utils.JsonToBytes(2, 0, "")) //无效的参数
		} else {
			sess := db.Mysql.NewSession()
			defer sess.Close()
			sess.Begin()
			user := &models.User{Status: fbd}
			rows, err := sess.Id(Id).Cols("Status").Update(user)
			if rows != 1 || err != nil {
				sess.Rollback()
				c.Ctx.ResponseWriter.Write(utils.JsonToBytes(0, 0, "")) //更新失败
			} else {
				sess.Commit()
				InsertOperationLog(c.Ctx, 0, Id, L_ForbiddenUser)
				c.Ctx.ResponseWriter.Write(utils.JsonToBytes(1, 1, fbd)) //更新成功
			}
		}
	}
}

//更新数据库的pwd
//param [id int](用户Id)
//param [pwd string](待更新的密码)
//return bool [true 成功][false 失败]
func updatePwd(id int, pwd string) bool {
	user := &models.User{Pwd: pwd}
	sess := db.Mysql.NewSession()
	defer sess.Close()
	sess.Begin()
	if rows, err := sess.Id(id).Update(user); rows != 1 || err != nil {
		sess.Rollback()
		return false
	} else {
		sess.Commit()
		return true
	}
}

//超级管理员重置一个用户的密码
//param [id int](用户id)
//param [pwd string](重置的密码)
func (c *UserController) ChangePwdOne() {
	if !checkIsSuperAdmin(c) {
		c.Ctx.ResponseWriter.Write(utils.JsonToBytes(6, 0, ""))
		return
	}
	if Id, err := c.GetInt("id"); err != nil || Id < 2 {
		c.Ctx.ResponseWriter.Write(utils.JsonToBytes(2, 0, "")) //参数错误
	} else {
		if updatePwd(Id, "e10adc3949ba59abbe56e057f20f883e") {
			InsertOperationLog(c.Ctx, 0, Id, L_ChangePwd)
			c.Ctx.ResponseWriter.Write(utils.JsonToBytes(1, 0, ""))
		} else {
			c.Ctx.ResponseWriter.Write(utils.JsonToBytes(0, 0, ""))
		}
	}
}

//重置自己的密码
//param [id int](用户id)
//param [oldpwd string](重置的密码)
//param [newpwd string](重置的密码)
func (c *UserController) ChangePwdSelf() {
	if Id, err := c.GetInt("id"); err != nil || Id < 0 {
		c.Ctx.ResponseWriter.Write(utils.JsonToBytes(2, 0, "")) //参数错误
	} else {
		if !checkIsSelf(c, Id) {
			c.Ctx.ResponseWriter.Write(utils.JsonToBytes(6, 0, "")) //不是本人？
			return
		}
		if pwd := c.GetString("oldpwd"); len(pwd) == 32 {
			if newpwd := c.GetString("newpwd"); len(newpwd) == 32 {
				if pwd == newpwd {
					c.Ctx.ResponseWriter.Write(utils.JsonToBytes(0, 0, "")) //新旧密码相同
					return
				}
				user := &models.User{Id: Id}
				ok, err := db.Mysql.Get(user)

				if ok || err != nil {
					if user.Pwd == pwd {
						user.Pwd = newpwd
						fmt.Println(user)
						rows, _ := db.Mysql.Id(Id).Update(user)
						if rows != 1 {
							c.Ctx.ResponseWriter.Write(utils.JsonToBytes(5, 0, "")) //更新数据库失败
						} else {
							InsertOperationLog(c.Ctx, Id, Id, L_ChangePwd)
							c.DelSession(SessionKey)
							c.Ctx.ResponseWriter.Write(utils.JsonToBytes(1, 0, "")) //更新成功
						}
					} else {
						c.Ctx.ResponseWriter.Write(utils.JsonToBytes(4, 0, "")) //旧密码错误
					}
				} else {
					c.Ctx.ResponseWriter.Write(utils.JsonToBytes(3, 0, "")) //没有这个人
				}
			} else {
				c.Ctx.ResponseWriter.Write(utils.JsonToBytes(2, 0, "")) //参数错误
			}
		} else {
			c.Ctx.ResponseWriter.Write(utils.JsonToBytes(2, 0, "")) //参数错误
		}
	}
}

//退出登录
func (c *UserController) Exit() {
	if Id, err := c.GetInt("id"); err != nil || Id <= 0 {
		c.Ctx.ResponseWriter.Write(utils.JsonToBytes(2, 0, "")) //参数错误
	} else {
		if !checkIsSelf(c, Id) {
			c.Ctx.ResponseWriter.Write(utils.JsonToBytes(6, 0, "")) //不是本人？
		} else {
			InsertOperationLog(c.Ctx, Id, Id, L_Logout)
			str := c.GetSession(SessionKey)
			if str != nil {
				GSessionUserMap.DeleteSession(str.(string))
			}
			c.DelSession(SessionKey)
			c.Ctx.ResponseWriter.Write(utils.JsonToBytes(1, 0, "")) //退出成功
		}
	}
}
